package com.warren.beans.factory.support;

import com.warren.beans.factory.DisposableBean;
import com.warren.beans.factory.ObjectFactory;
import com.warren.beans.factory.config.SingletonBeanRegistry;
import com.warren.error.BeansException;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author warren
 * @create 2021-08-17 20:53
 * @Description 单例注册实现
 */
public class DefaultSingletonBeanRegistry implements SingletonBeanRegistry {

    /**
     * Internal marker for a null singleton object:
     * used as marker value for concurrent Maps (which don't support null values).
     */
    protected static final Object NULL_OBJECT = new Object();

    //一级缓存普通对象
    private Map<String, Object> singletonObjects = new HashMap<>();

    // 二级缓存，提前暴漏对象，没有完全实例化的对象
    protected final Map<String, Object> earlySingletonObjects = new HashMap<String,Object>();

    // 三级缓存，存放代理对象
    private final Map<String, ObjectFactory<?>> singletonFactories = new HashMap<String, ObjectFactory<?>>();

    private final Map<String, DisposableBean> disposableBeans = new HashMap<>();

    @Override
    public Object getSingleton(String beanName) {
        Object singletonObject = singletonObjects.get(beanName);
        if (null == singletonObject){
            singletonObject = earlySingletonObjects.get(beanName);
            //判断二级缓存是否有对象，这个对象就是代理对象，因为只有代理对象才会放到三级缓存中,三级对象池，把对象放到二级对象池中
            if (null == singletonObject){
                ObjectFactory<?> singletonFactory = singletonFactories.get(beanName);
                if (singletonFactory != null){
                    singletonObject = singletonFactory.getObject();
                    //把三级缓存中的代理对象中的真实对象获取出来，放入二级缓存中
                    earlySingletonObjects.put(beanName,singletonObject);
                    singletonFactories.remove(beanName);
                }
            }
        }
        return singletonObject;
    }

    @Override
    public void registerSingleton(String beanName, Object singletonObject) {
        singletonObjects.put(beanName, singletonObject);
        //删除掉二三级的
        earlySingletonObjects.remove(beanName);
        singletonFactories.remove(beanName);
    }

    //protected  void addSingleton(String beanName,Object singletonObject){
    //    singletonObjects.put(beanName,singletonObject);
    //}

    /**
     * 添加到代理单例中
     * @param beanName
     * @param singletonFactory
     */
    protected void addSingletonFactory(String beanName,ObjectFactory<?> singletonFactory){
        if (!this.singletonFactories.containsKey(beanName)){
            this.singletonFactories.put(beanName,singletonFactory);
            this.earlySingletonObjects.remove(beanName);
        }
    }

    public void  registerDisposableBean(String beanName,DisposableBean bean){
        disposableBeans.put(beanName,bean);
    }

    public void destroySingletons(){
        Set<String> keySet = this.disposableBeans.keySet();
        Object[] disposableBeanNames = keySet.toArray();

        for (int i = disposableBeanNames.length - 1; i >= 0; i--) {
            Object beanName = disposableBeanNames[i];
            DisposableBean disposableBean = disposableBeans.remove(beanName);
            try {
                disposableBean.destroy();
            } catch (Exception e) {
                throw new BeansException("Destroy method on bean with name '" + beanName + "' threw an exception", e);
            }
        }
    }
}
